/**
 * Copyright 2007 Christian Mueller
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
 * use this file except in compliance with the License. You may obtain a copy of 
 * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by 
 * applicable law or agreed to in writing, software distributed under the License 
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
 * either express or implied. See the License for the specific language governing 
 * permissions and limitations under the License.
 * 
 * Description:
 * This contains the functions to parse the commandline, against the defined
 * parameters
 * 
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "myglobal.h"
#include "options.h"

/******* Parsing of the parameters ************/

/**
 * This function parses a command-line
 */
int options_parse_parameter(options_param parameters[],int argc, char *argv[],int pos)
{ 
	#ifdef DEBUG_OPTIONS
		printf("\n\nParsing parameter: %s \n",argv[pos]);
	#endif
	/** walk throu all parameters **/
	int i = 0;
	while (parameters[i].type!=OPTION_NULL) {
		
		options_param param = parameters[i];
		int found = 0;
		 
		// is it a shortname (add leading -)
		#ifdef DEBUG_OPTIONS
			printf("\n\nParsing against: %s \n",param.shortname);
		#endif
		if (param.shortname!=NULL && 
			strncmp("-",argv[pos],1)==0 &&
			strcmp(param.shortname,argv[pos]+1)==0)
			found = 1;
		
		// is it the longname
		#ifdef DEBUG_OPTIONS
			printf("\n\nParsing against: %s \n",param.longname);
		#endif
		if (param.longname!=NULL && 
			strncmp("--",argv[pos],2)==0 &&
			strcmp(param.longname,argv[pos]+2)==0)
					found = 1;
			
		
		if (found == 1) {
			int temp;
			switch (param.type) {
				case OPTION_STRING:
					/** This option set a string **/
					
					/* Check if parameter is missing */
					if (argv[pos+1]==NULL) {
						/* Yes it is missing! */
						printf("<string> is missing!\n");
						return 0;	
					}
					if (strlen(argv[pos+1])>=OPTIONS_MAX_STRING) {
						printf("Option Parameter is too long: %s",argv[pos+1]);
						return 8;	
					}
					strcpy(param.variable,argv[pos+1]);
					return 2; // didn't read the next parameter please
					break;
				case OPTION_BOOLEAN_TRUE:
					/* Sets parameter to true */
					temp=TRUE;
					memcpy(param.variable,(void*)&temp,sizeof(int));
					return 1;
					break;
				case OPTION_BOOLEAN_FALSE:
					/* Sets parameter to false */
					temp=FALSE;
					memcpy(param.variable,(void*)&temp,sizeof(int));
					return 1;
					break;
				case OPTION_INTEGER:
					/* Check if parameter is missing */
					if (argv[pos+1]==NULL) {
						/* Yes it is missing! */
						printf("<integer> is missing!\n");
						return 0;	
					}
					
					/* Sets parameter to true */
					temp = atoi(argv[pos+1]);
					memcpy(param.variable,(void*)&temp,sizeof(int));
					return 2;
					break;
				case OPTION_DESCRIPTION:
				case OPTION_NULL:
					break; // ignore				
			} // end-switch
		} // end-if found == TRUE
				
		i++;	
	}
	printf("Unknown parameter %s!\n",argv[i]);
	return 0; /** Error: Unknown parameter **/
}

/**
 * This function parses the command line starting at the defined position
 */
int options_parse(options_param parameters[],int argc, char *argv[],int startposition)
{
	if (startposition>=argc) {
		printf("Error not enough parameters found to parse commandline");
		return 8;		
	}
	int i = startposition;
	while (i<argc) {
		int anz = options_parse_parameter(parameters,argc,argv,i);
		if (anz==0) {
			/** If error appeard! **/
			return 8;	
		}
		i+=anz;	
	}
	return 0;	
}

/******* Generating of the usage help ************/

/**
 * This command prints the lines for one parameter 
 **/
void options_printparameter(options_param parameter)
{
	if (parameter.type != OPTION_DESCRIPTION) {
		printf("\n   ");	/* First New Line */
		if (parameter.shortname!=NULL) {
			printf("-%s",parameter.shortname);
			
			if (parameter.longname!=NULL) /* if there is also a longname print a comma */
			printf(", "); 	
		}
		if (parameter.longname!=NULL) {
			printf("--%s",parameter.longname);	
		}
		switch(parameter.type) {
			case OPTION_STRING:
				printf(" <string>");
				break;
			case OPTION_INTEGER:
				printf(" <integer>");
				break;
			case OPTION_BOOLEAN_TRUE: 
			case OPTION_BOOLEAN_FALSE:
				break; // Nothing
			default:
				printf(" ERROR NOT DEFINED!!!!!! ");		
		}
		printf("\n"); // newline
		printf("           ");
	} else {
		printf("\n");
	}
	
	printf("%s",parameter.description);
	printf("\n"); // newline
	
}

/**
 * This command print the usage for all parameters defined
 */
void options_printusage(options_param parameters[])
{
	int position = 0;
	while (parameters[position].type!=OPTION_NULL) {
		options_param param = parameters[position];
		options_printparameter(param);
		position++;	
	}
	
}

